﻿#region "Copyright (C) Lenny Granovsky. 2005-2013"
//This program is free software distribute under the terms of the GNU General Public License as published by
//the Free Software Foundation. Please read AssemblyInfo.cs file for more information.
#endregion

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Web.Services.Protocols;
using System.Web;
using System.Web.Caching;
using System.Web.UI;

namespace Web.Enhancements.Rest.InfoCaching
{
    [Serializable()]
    internal class MethodInfoCacheItem
    {
        public LogicalMethodInfo Method { get; set; }
        public string MethodKey { get; private set; }
        public System.Web.SessionState.SessionStateBehavior SessionMode { get; set; }
        public string ContentType { get; set; }
        public string ContentDisposition { get; set; }
        /// <summary>
        /// Gets or sets the JSON serializer type when the JSON is used as output. 
        /// The default value is standard JavaScriptSerializer.
        /// </summary>
        public JsonSerializerType JsonSerializer { get; set; }
        public WebRestCacheParameters CacheParameters { get; set; }
        /// <summary>
        /// Gets or set information about parameter when its data should be loaded directly from the request input stream (HTTP message body).
        /// </summary>
        public HttpBodyParameterInstructions HttpBodyParameterInfo { get; set; }
        internal List<Filters.IWebRestFilterAttribute> FilterAttributes { get; set; }

        public string MethodName
        {
            get { return Method.Name; }
        }

        public MethodInfoCacheItem(LogicalMethodInfo method)
        {
            this.Method = method;
            this.MethodKey = MethodInfoCache.CreateKey(method.MethodInfo.DeclaringType.Name.ToLower(), method.Name.ToLower());
            object[] tmp = method.MethodInfo.GetCustomAttributes(typeof(WebRestMethodAttribute), false);
            this.SessionMode = System.Web.SessionState.SessionStateBehavior.Default;
            this.JsonSerializer = JsonSerializerType.JavaScriptSerializer;
            if (tmp.Length > 0)
            {
                WebRestMethodAttribute tmpAttr1 = (tmp[0] as WebRestMethodAttribute);
                this.SessionMode = tmpAttr1.SessionMode;
                this.ContentType = tmpAttr1.ContentType;
                this.ContentDisposition = tmpAttr1.ContentDisposition;
                this.JsonSerializer = tmpAttr1.JsonSerializer;
            }
            else
                throw new WebRestException(ErrorMessages.ResourceManager.GetString("InvalidMethodNoWebRestMethodAttribute"), method.Name);
            //read cache configuration
            this.CacheParameters = new WebRestCacheParameters();
            tmp = method.MethodInfo.GetCustomAttributes(typeof(WebRestCacheAttribute), false);
            if (tmp.Length > 0)
            {
                WebRestCacheAttribute tmpAttr2 = (tmp[0] as WebRestCacheAttribute);
                this.CacheParameters.Duration = tmpAttr2.Duration;
                this.CacheParameters.Enabled = tmpAttr2.Enabled;
                this.CacheParameters.Location = tmpAttr2.Location;
                this.CacheParameters.VaryByParam = tmpAttr2.VaryByParam.Replace(" ", "");
                this.CacheParameters.VaryByParamItems.Add("method");
                if (string.Compare(tmpAttr2.VaryByParam, "All", true) == 0)
                    this.CacheParameters.VaryByParamItems.AddRange(method.Parameters.Select(p => p.Name));
                else if (!string.IsNullOrEmpty(tmpAttr2.VaryByParam) && string.Compare(tmpAttr2.VaryByParam, "None", true) != 0)
                    this.CacheParameters.VaryByParamItems.AddRange(tmpAttr2.VaryByParam.Split(new char[] { ';', ',' }));
            }

            if (this.ContentType == null)
                this.ContentType = "";
            if (this.ContentDisposition == null)
                this.ContentDisposition = "";

            //read PostParameterAttribute
            tmp = method.MethodInfo.GetCustomAttributes(typeof(HttpBodyParameterAttribute), false);
            this.HttpBodyParameterInfo = new HttpBodyParameterInstructions();
            if (tmp.Length > 0)
            {
                HttpBodyParameterAttribute tmpAttr3 = (tmp[0] as HttpBodyParameterAttribute);
                this.HttpBodyParameterInfo.ParameterName = tmpAttr3.ParameterName;
                this.HttpBodyParameterInfo.ConversionHint = tmpAttr3.ConversionHint;
                this.HttpBodyParameterInfo.UseCustomJsonDeserialiser = tmpAttr3.UseCustomJsonDeserialiser;
            }

            //build list of REST Filters
            this.FilterAttributes = new List<Filters.IWebRestFilterAttribute>();
            object[] attrs = method.DeclaringType.GetCustomAttributes(typeof(Filters.IWebRestFilterAttribute), false)
                .OrderBy(a => ((Filters.IWebRestFilterAttribute)a).Priority).ToArray();
            if (attrs != null)
            {
                foreach (object attr in attrs)
                    this.FilterAttributes.Add((Filters.IWebRestFilterAttribute)attr);
            }
            attrs = method.GetCustomAttributes(typeof(Filters.IWebRestFilterAttribute))
                .OrderBy(a => ((Filters.IWebRestFilterAttribute)a).Priority).ToArray();
            if (attrs != null)
            {
                foreach (object attr in attrs)
                    this.FilterAttributes.Add((Filters.IWebRestFilterAttribute)attr);
            }
        }
    }
}
